﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Slwy.FrameCore.Dependency
{
    using System.Reflection;

    using Microsoft.Extensions.DependencyInjection;

    using Slwy.FrameCore.Reflection;

    /// <summary>
    /// 依赖注入构建器基类，从程序集中反射进行依赖注入接口与实现的注册
    /// </summary>
    public abstract class IocBuilderBase : IIocBuilder
    {
        private readonly IServiceCollection _services;
        private bool _isBuilded;
        private IServiceProvider _provider;

        public IocBuilderBase(IServiceCollection services)
        {
            this.AssemblyFinder = new DirectoryAssemblyFinder();
            this._services = services;
        }

        /// <summary>
        /// 获取或者设置 程序集查找器
        /// </summary>
        public IAllAssemblyFinder AssemblyFinder { get; set; }

        public IServiceProvider ServiceProvider
        {
            get
            {
                if (this._isBuilded)
                {
                    return this._provider;
                }

                this._provider = this.Build();
                this._isBuilded = true;
                return this._provider;
            }
        }

        /// <summary>
        /// 开始构建依赖注入映射
        /// </summary>
        /// <returns>注入的服务. </returns>
        public IServiceProvider Build()
        {
            if (this._isBuilded)
            {
                return this._provider;
            }

            Assembly[] assemblies = this.AssemblyFinder.FindAll();

            this.AddCustomTypes(this._services);

            this._provider = this.BuildAndSetResolver(this._services, assemblies);
            this._isBuilded = true;
            return this._provider;
        }

        /// <summary>
        /// 添加自定义服务映射
        /// </summary>
        /// <param name="services">服务信息集合</param>
        protected virtual void AddCustomTypes(IServiceCollection services)
        {
        }

        /// <summary>
        /// 重写以实现构建服务并设置各个平台的Resolver
        /// </summary>
        /// <param name="services">服务映射信息集合</param>
        /// <param name="assemblies">要检索的程序集集合</param>
        /// <returns>服务提供者</returns>
        protected abstract IServiceProvider BuildAndSetResolver(IServiceCollection services, Assembly[] assemblies);
    }
}
